const path = require('path')
const fs = require('fs')
const vm = require('vm');

function Module(id) {
  this.id = id;
  this.exports = {}
}
Module._extensions = {
  '.js'(module) {
    const content = fs.readFileSync(module.id, 'utf8');
    let wrapperFn = vm.compileFunction(content, [
      'exports', 'require', 'module', '__filename', '__dirname' // 都是参数
    ]);
    let exports = this.exports;
    let thisValue = exports
    let require = req;
    let filename = module.id
    let dirname = path.dirname(filename);

    // 交给用户去赋值
    Reflect.apply(wrapperFn, thisValue, [exports, require, module, filename, dirname])
  },
  '.json'(module) { // vite的源码里面为了能加载.vue文件
    const content = fs.readFileSync(module.id, 'utf8');
    module.exports = JSON.parse(content)
  }
}
Module._resolveFilename = function (id) {
  const filepath = path.resolve(id);
  if (fs.existsSync(filepath)) return filepath

  const exts = Object.keys(Module._extensions);

  // 尝试添加后缀
  for (let i = 0; i < exts.length; i++) {
    let file = filepath + exts[i];
    if (fs.existsSync(file)) return file
  }
  throw new Error('Cannot find module:' + id)
}

Module.prototype.load = function (filename) {
  let ext = path.extname(filename);
  Module._extensions[ext](this);
}
Module._cache = {}
function req(id) {
  let absPath = Module._resolveFilename(id);
  let existsModule = Module._cache[absPath];
  if (existsModule) {
    return existsModule.exports; // 直接利用上次缓存的结果即可
  }
  const module = new Module(absPath); // id , exports  会将导出的结果放到exports上
  Module._cache[absPath] = module; // 缓存对应的模块
  module.load(absPath)
  return module.exports;
}
